import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { CreateBookingDto } from './dto/create-booking.dto';
import { UpdateBookingDto } from './dto/update-booking.dto';
import { InjectEntityManager } from '@nestjs/typeorm';
import {
  Between,
  EntityManager,
  LessThanOrEqual,
  Like,
  MoreThanOrEqual,
} from 'typeorm';
import { User } from '../user/entities/user.entity';
import { MeetingRoom } from '../meeting-room/entities/meeting-room.entity';
import { Booking } from './entities/booking.entity';
import { RedisService } from '../redis/redis.service';
import { EmailService } from '../email/email.service';

@Injectable()
export class BookingService {
  @InjectEntityManager()
  private entityManager: EntityManager;

  @Inject(RedisService)
  private redisService: RedisService;

  @Inject(EmailService)
  private emailService: EmailService;

  async find(
    pageNo: number,
    pageSize: number,
    username: string,
    meetingRoomName: string,
    meetingRoomPosition: string,
    bookingTimeRangeStart: number,
    bookingTimeRangeEnd: number,
  ) {
    const skipCount = (pageNo - 1) * pageSize;

    const condition: Record<string, any> = {};

    if (username) {
      condition.user = { username: Like(`%${username}%`) };
    }

    if (meetingRoomName) {
      condition.room = { name: Like(`%${meetingRoomName}%`) };
    }

    if (meetingRoomPosition) {
      if (condition.room) {
        condition.room = {};
      }
      condition.room = { location: Like(`%${meetingRoomPosition}%`) };
    }

    if (bookingTimeRangeStart) {
      if (!bookingTimeRangeEnd) {
        bookingTimeRangeEnd = bookingTimeRangeStart + 60 * 60 * 1000;
      }
      condition.startTime = Between(
        new Date(bookingTimeRangeStart),
        new Date(bookingTimeRangeEnd),
      );
    }

    const [bookings, totalCount] = await this.entityManager.findAndCount(
      Booking,
      {
        where: condition,
        relations: {
          user: true,
          room: true,
        },
        skip: skipCount,
        take: pageSize,
      },
    );

    return {
      bookings: bookings.map((item) => {
        if (item.user) {
          delete (item.user as any).password;
        }
        return item;
      }),
      totalCount,
    };
  }

  async add(bookingDto: CreateBookingDto, userId: number) {
    const meetingRoom = await this.entityManager.findOne(MeetingRoom, {
      where: { id: bookingDto.meetingRoomId },
    });

    if (!meetingRoom) {
      throw new BadRequestException('会议室不存在');
    }

    const user = await this.entityManager.findOneBy(User, { id: userId });

    const booking = new Booking();
    booking.room = meetingRoom;
    booking.user = user as User;
    booking.startTime = new Date(bookingDto.startTime);
    booking.endTime = new Date(bookingDto.endTime);

    const res = await this.entityManager.findOneBy(Booking, {
      room: { id: meetingRoom.id },
      startTime: LessThanOrEqual(booking.startTime),
      endTime: MoreThanOrEqual(booking.endTime),
    });

    if (res) {
      throw new BadRequestException('该时间段已被占用');
    }

    await this.entityManager.save(Booking, booking);

    return 'success';
  }

  // TODO: 已驳回和已解除的不能通过，驳回和解除接口也要有类似的逻辑，此处暂不处理
  async apply(id: number) {
    await this.entityManager.update(
      Booking,
      { id },
      {
        status: '审核通过',
      },
    );
    return 'success';
  }

  async reject(id: number) {
    await this.entityManager.update(Booking, { id }, { status: '审核驳回' });
    return 'success';
  }

  async unbind(id: number) {
    await this.entityManager.update(Booking, { id }, { status: '已解除' });
    return 'success';
  }

  async urge(id: number) {
    const flag = await this.redisService.get(`urge_${id}`);

    if (flag) {
      return '半小时内只能催办一次，请耐心等待';
    }

    let email = await this.redisService.get('admin_email');

    if (!email) {
      const admin = await this.entityManager.findOne(User, {
        select: { email: true },
        where: { isAdmin: true },
      });

      if (admin) {
        email = admin.email;
        console.log('email:', email);
        await this.redisService.set('admin_email', email, 30 * 60);
        console.log('email set done');
      } else {
        throw new BadRequestException('系统问题，请联系管理员');
      }
    }

    this.emailService.sendMail({
      to: email,
      subject: '预定申请催办提醒',
      html: `id 为 ${id} 的预定申请正在等待审批`,
    });

    this.redisService.set(`urge_${id}`, 1, 30 * 60);
  }
}
